package com.ferryc.modules.sys.web;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ferryc.commons.annotation.SystemLog;
import com.ferryc.commons.csrf.CookieCsrfTokenRepository;
import com.ferryc.commons.csrf.CsrfToken;
import com.ferryc.commons.exception.BaseException;
import com.ferryc.commons.shiro.ShiroDbRealm;
import com.ferryc.commons.utils.DigestUtil;
import com.ferryc.commons.utils.StringUtil;
import com.ferryc.commons.utils.WebUtil;
import com.ferryc.commons.web.BaseController;
import com.ferryc.constant.ResultConstant;
import com.ferryc.modules.sys.util.UserUtils;

/**
 * @description：登录退出
 * @author：zhixuan.wang
 * @date：2015/10/1 14:51
 */
@Controller
public class LoginController extends BaseController {

	/**
	 * 首页
	 *
	 * @return
	 */
	@GetMapping("/")
	public String index() {
		return "redirect:/index";
	}

	/**
	 * GET 登录
	 * 
	 * @return {String}
	 */
	@GetMapping("/login")
	@CsrfToken(create = true)
	public String login() {
		logger.info("GET请求登录");
		if (SecurityUtils.getSubject().isAuthenticated()) {
			return "redirect:/index";
		}
		return "login";
	}

	/**
	 * POST 登录 shiro 写法
	 *
	 * @param username
	 *            用户名
	 * @param password
	 *            密码
	 * @return {Object}
	 */
	@PostMapping("/login")
	@CsrfToken(remove = true)
	@ResponseBody
	@SystemLog(module = "登录", methods = "用户登录")
	public Object loginPost(HttpServletRequest request, String username, String password, @RequestParam(value = "rememberMe", defaultValue = "1") Integer rememberMe) {
		logger.info("POST请求登录");
		// 改为全部抛出异常，避免ajax csrf token被刷新
		if (StringUtil.isBlank(username)) {
			throw new BaseException(ResultConstant.EMPTY_USERNAME);
		}
		if (StringUtil.isBlank(password)) {
			throw new BaseException(ResultConstant.EMPTY_PASS);
		}
		/*
		 * if (StringUtils.isBlank(captcha)) { throw new
		 * BaseExcetion("验证码不能为空"); }
		 * 
		 * if (!CaptchaUtils.validate(request, captcha)) { throw new
		 * BaseExcetion("验证码错误"); }
		 */
		String pwd = DigestUtil.decrypt3Des(password, WebUtil.getCookieValue(request, CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME).replaceAll("-", ""));
		Subject user = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(username, pwd);
		// 设置记住密码
		token.setRememberMe(1 == rememberMe);
		try {
			user.login(token);
			return renderSuccess(ResultConstant.LOGIN_SUCCESS);
		} catch (UnknownAccountException | DisabledAccountException | IncorrectCredentialsException e) {
			logger.error(e.getMessage(), e);
			return renderError(ResultConstant.ERR_USER_PW);
		} catch (ExcessiveAttemptsException e) {
			logger.error(e.getMessage(), e);
			return renderError(ResultConstant.ERR_PW_LIMIT);
			/*
			 * } catch (LockedAccountException e) { logger.error(e.getMessage(),
			 * e); return renderError(LoginConstant.USERNAME_LOCKED);
			 */
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return renderError(ResultConstant.ERR_UNKNOWN);
		}

	}

	/**
	 * 未授权
	 * 
	 * @return {String}
	 */
	@GetMapping("/unauth")
	public String unauth() {
		if (SecurityUtils.getSubject().isAuthenticated() == Boolean.FALSE) {
			return "redirect:/login";
		}
		return "unauth";
	}

	/**
	 * 退出
	 * 
	 * @return {Result}
	 */
	@GetMapping("/logout")
	@SystemLog(module = "登录", methods = "用户登出")
	public String logout() {
		logger.info("登出");
		Subject subject = SecurityUtils.getSubject();
		subject.logout();
		return "redirect:/login";
	}
}
